/**
 * 模板加载器 - 提供模板相关功能的可组合函数
 * 
 * 该模块负责:
 * 1. 默认模板的生成和加载
 * 2. 根据不同打印类型获取相应的默认字段
 * 3. 处理模板导入/导出功能
 */

import { ref } from 'vue';
import { ElMessage } from 'element-plus';

/**
 * 创建模板加载功能
 * @param {Object} options 配置选项
 * @param {Object} options.printTemplateFields 打印模板字段配置
 * @param {Function} options.clearCanvas 清空画布的函数
 * @param {Function} options.updateRulerDimensions 更新刻度尺尺寸的函数
 * @param {Function} options.mmToPx 毫米转像素的函数
 * @param {number} options.pxPerMm 像素每毫米
 * @param {Function} options.applyPaperSettings 应用纸张设置的函数
 * @param {Function} options.setPxPerMm 设置像素毫米比例的函数
 * @param {Object} options.templateType 模板类型
 * @param {Function} options.adjustPaperSettingsByType 根据模板类型调整纸张设置的函数
 * @param {Object} options.printFields 打印字段选项
 * @param {Object} options.handleFieldSelected 回显右侧面板字段
 * @returns {Object} 模板加载相关的方法和属性
 */
export default function useTemplateLoader(options = {}) {
  const {
    printTemplateFields,
    clearCanvas,
    updateRulerDimensions,
    mmToPx,
    pxPerMm,
    applyPaperSettings,
    setPxPerMm,
    templateType,
    adjustPaperSettingsByType,
    printFields,
    handleFieldSelected,
    setTableData
  } = options;

  /**
   * 获取默认模板名称
   * @param {string} type 打印类型
   * @returns {string} 模板名称
   */
  const getDefaultTemplateName = (type) => {
    console.log(`获取打印类型[${type}]的默认模板名称`);
    return printTemplateFields[type]?.title || '打印模板';
  };


  /**
   * 加载默认模板到画布
   * @param {string} type 打印类型
   * @param {Object} fabric Fabric.js实例
   */
  const loadDefaultTemplate = (type, fabric) => {
    if (typeof window === 'undefined' || !window.globalCanvas) {
      console.error('画布未初始化，无法加载默认模板');
      return;
    }

    console.log(`开始加载默认模板，类型: ${type}`);

    try {
     

    } catch (error) {
      console.error('加载默认模板时出错:', error);
      ElMessage.error(`加载默认模板失败: ${error.message}`);
    }
  };

  /**
   * 创建条形码字段
   * @param {Object} fieldConfig 字段配置
   * @param {Object} position 位置信息
   */
  const createBarcodeField = (fieldConfig, position) => {
    if (typeof JsBarcode !== 'undefined') {
      try {
        // 创建一个临时的canvas元素
        const tempCanvas = document.createElement('canvas');
        tempCanvas.width = 300;
        tempCanvas.height = 100;

        // 确保tempCanvas已添加到DOM中
        tempCanvas.style.display = 'none';
        document.body.appendChild(tempCanvas);

        // 使用JsBarcode生成条形码
        JsBarcode(tempCanvas, '12345678', {
          format: 'CODE128',
          width: 2,
          height: 80,
          displayValue: true,
          fontSize: 14,
          textMargin: 2,
          margin: 10,
          background: '#FFFFFF',
          lineColor: '#000000'
        });

        // 从临时canvas获取数据URL
        const dataUrl = tempCanvas.toDataURL('image/png');
        console.log('条形码数据URL生成成功:', dataUrl.substring(0, 50) + '...');

        // 从DOM中移除临时canvas
        document.body.removeChild(tempCanvas);

        // 使用fabric.js添加到画布
        window.fabric.Image.fromURL(dataUrl)
          .then(img => {
            console.log('条形码图片创建成功:', img);

            if (!img) {
              console.error('创建条形码图片对象失败');
              ElMessage.error(`添加条形码 ${fieldConfig.label} 失败`);
              return;
            }

            // 设置图片属性
            img.set({
              left: mmToPx(position.x),
              top: mmToPx(position.y),
              borderColor: '#5E9ED6',
              cornerColor: '#5E9ED6',
              cornerSize: 6,
              transparentCorners: false,
              selectable: true,
              customType: 'barcode',
              fieldName: fieldConfig.key,
              fieldType: 'barcode',
              barcodeValue: '12345678',
              textTemplate: fieldConfig.textTemplate || '${data}'
            });

            // 添加到画布
            window.globalCanvas.add(img);
            window.globalCanvas.renderAll();
            console.log(`条形码 ${fieldConfig.label} 添加成功`);
          })
          .catch(error => {
            console.error('加载条形码图片失败:', error);
            ElMessage.error(`添加条形码 ${fieldConfig.label} 失败: 图片加载错误`);
          });
      } catch (error) {
        console.error(`添加条形码失败:`, error);
        ElMessage.error(`添加条形码 ${fieldConfig.label} 失败: ${error.message}`);
      }
    } else {
      console.error('JsBarcode库未加载，无法创建条形码');
      ElMessage.error('条形码库未加载，请确保已引入JsBarcode');
    }
  };

  /**
   * 创建文本字段
   * @param {Object} fieldConfig 字段配置
   * @param {Object} position 位置信息
   */
  const createTextField = (fieldConfig, position) => {
    // 添加文本
    const textObj = new window.fabric.Textbox(fieldConfig.textTemplate, {
      left: mmToPx(position.x),
      top: mmToPx(position.y),
      fontSize: fieldConfig.style.fontSize,
      fontWeight: fieldConfig.style.bold ? 'bold' : 'normal',
      fill: fieldConfig.style.color,
      width: mmToPx(45),
      customType: 'field', // 修改为customType适配Fabric.js v6
      fieldName: fieldConfig.key,
      fieldType: fieldConfig.type,
      originX: 'left',
      originY: 'top'
    });

    window.globalCanvas.add(textObj);
    console.log(`文本字段 ${fieldConfig.label} 添加成功`);
  };

  /**
   * 加载模板数据
   * @param {string} templateId 模板ID
   */
  const loadTemplateData = (templateId) => {
    if (!templateId) {
      console.warn('模板ID为空，无法加载模板数据');
      return;
    }

    console.log(`开始加载模板, ID: ${templateId}`);

    // 这里应该从后端加载模板数据
    // 模拟加载过程
    ElMessage.info('正在加载模板数据...');

    // 示例：加载演示模板
    setTimeout(() => {
      if (typeof window !== 'undefined' && window.globalCanvas) {
        ElMessage.success('模板加载成功');
      }
    }, 500);
  };

  /**
   * 导出模板到JSON
   * @returns {string} JSON格式的模板数据
   */
  const exportTemplateToJson = () => {
    if (typeof window === 'undefined' || !window.globalCanvas) {
      console.error('画布未初始化，无法导出模板');
      return null;
    }

    try {
      // 获取画布尺寸和像素毫米比例 - 确保使用原始值
      // 检测是否为ref对象，如果是则使用.value获取值
      const effectivePxPerMm = typeof pxPerMm === 'object' && pxPerMm.value !== undefined
        ? pxPerMm.value
        : (pxPerMm || (window.globalCanvas ? (window.globalCanvas.width / 210) : 3.78));

      console.log('导出模板使用的pxPerMm:', effectivePxPerMm);

      // 获取当前画布实际尺寸（毫米）
      const canvasWidth = window.globalCanvas.width / effectivePxPerMm;
      const canvasHeight = window.globalCanvas.height / effectivePxPerMm;

      // 获取模板类型（如果有传入）
      const templateTypeValue = typeof templateType === 'object' && templateType.value !== undefined
        ? templateType.value
        : (templateType || 'general');

      // 获取画布上所有对象
      const objects = window.globalCanvas.getObjects();

      // 创建简化的对象数据
      const exportObjects = objects.map(obj => {
        // 基本属性（所有对象都具有的通用属性）
        const baseObject = {
          // 位置和尺寸（以毫米为单位）
          left: Math.round((obj.left / effectivePxPerMm) * 100) / 100, // 保留两位小数
          top: Math.round((obj.top / effectivePxPerMm) * 100) / 100,
          width: Math.round(((obj.width * obj.scaleX) / effectivePxPerMm) * 100) / 100,
          height: Math.round(((obj.height * obj.scaleY) / effectivePxPerMm) * 100) / 100,
          angle: obj.angle || 0,
          type: obj.type, // 对象类型
          fieldName: obj.fieldName, // 字段名称
          fieldType: obj.fieldType || 'text',   
          customType: obj.customType || '',
        };

        // 根据不同类型添加特定属性
        if (obj.customType === 'field' || obj.type === 'textbox' || obj.type === 'i-text' || obj.type === 'text') {
          // 文本字段
          return {
            ...baseObject,
			initialData: JSON.stringify({
			  key: obj.customData.key || '',
			  label: obj.customData.label || '',
			  type: obj.customData.type || '',
			  textTemplate: obj.text,
			  position: { x: Math.round((obj.left / effectivePxPerMm) * 100) / 100, y: Math.round((obj.top / effectivePxPerMm) * 100) / 100 },
			  left: Math.round((obj.left / effectivePxPerMm) * 100) / 100, // 保留两位小数
			  top: Math.round((obj.top / effectivePxPerMm) * 100) / 100,
			  style: { fontSize: obj.customData.style.fontSize*obj.scaleX, bold: false, color: "#000" },
			  barcodeFormat: obj.customData.type === 'barcode' ? (obj.barcodeFormat || 'CODE128') : undefined,
			  displayValue: obj.customData.type === 'barcode' ? (obj.displayValue || true) : undefined,
			  width: Math.round(((obj.width * obj.scaleX) / effectivePxPerMm) * 100) / 100,
			  height: Math.round(((obj.height * obj.scaleY) / effectivePxPerMm) * 100) / 100,
			  scaleX: obj.scaleX || '',
			  scaleY: obj.scaleY || '',
			  angle: obj.angle || '',
			  fontWeight: obj.fontWeight || '',
			  border: obj.customData.border || '',
			  barcodeValue:obj.barcodeValue,
			}),
            type: 'text',
            text: obj.text || '',
            fontFamily: obj.fontFamily || 'Arial',
            fontSize: Math.round((obj.fontSize / effectivePxPerMm) * 100) / 100,
            fontWeight: obj.fontWeight || 'normal',
            fontStyle: obj.fontStyle || 'normal',
            textAlign: obj.textAlign || 'left',
            fill: obj.fill || '#000000',
           
            textTemplate: obj.textTemplate || obj.text || '${data}'
          };
        } else if (obj.customType === 'barcode' || obj.objectType === 'barcode') {
          // 条形码
          return {
            ...baseObject,
			initialData: JSON.stringify({
			  key: obj.customData.key || '',
			  label: obj.customData.label || '',
			  type: obj.customData.type || '',
			  textTemplate: obj.customData.textTemplate || '',
			  position: { x: Math.round((obj.left / effectivePxPerMm) * 100) / 100, y: Math.round((obj.top / effectivePxPerMm) * 100) / 100 },
			  left: Math.round((obj.left / effectivePxPerMm) * 100) / 100, // 保留两位小数
			  top: Math.round((obj.top / effectivePxPerMm) * 100) / 100,
			  style: { fontSize: obj.customData.style.fontSize*obj.scaleX, bold: false, color: "#000" },
			  barcodeFormat: obj.customData.type === 'barcode' ? (obj.barcodeFormat || 'CODE128') : undefined,
			  displayValue: obj.customData.type === 'barcode' ? (obj.displayValue || true) : undefined,
			  width: Math.round(((obj.width * obj.scaleX) / effectivePxPerMm) * 100) / 100,
			  height: Math.round(((obj.height * obj.scaleY) / effectivePxPerMm) * 100) / 100,
			  scaleX: obj.scaleX || '',
			  scaleY: obj.scaleY || '',
			  angle: obj.angle || '',
			  fontWeight: obj.fontWeight || '',
			  border: obj.customData.border || '',
			  barcodeValue:obj.barcodeValue
			}),
            type: 'barcode',
            barcodeValue: obj.barcodeValue || '12345678',
            barcodeFormat: obj.barcodeFormat || 'CODE128',
            displayValue: obj.displayValue !== undefined ? obj.displayValue : true,
            textTemplate: obj.textTemplate || '${data}'
          };
        } else if (obj.customType === 'qrcode' || obj.objectType === 'qrcode') {
          // 二维码
          return {
            ...baseObject,
            type: 'qrcode',
            qrcodeValue: obj.qrcodeValue || 'test',
            fieldName: obj.fieldName,
            textTemplate: obj.textTemplate || '${data}'
          };
        } else if (obj.type === 'image') {
          // 图片
          let src = '';
          if (obj.cacheKey && obj._cacheCanvas) {
            try {
              src = obj._cacheCanvas.toDataURL('image/png');
            } catch (e) {
              console.warn('无法导出图片内容:', e);
            }
          }

          return {
            ...baseObject,
            type: 'image',
            src: src,
            isBackground: obj.customType === 'background'
          };
        } else if (obj.type === 'rect') {
          // 矩形
          return {
            ...baseObject,
            type: 'rect',
            fill: obj.fill || 'transparent',
            stroke: obj.stroke || '#000000',
            strokeWidth: Math.round(((obj.strokeWidth || 1) / effectivePxPerMm) * 100) / 100
          };
        } else if (obj.type === 'line') {
          // 线条
          return {
            ...baseObject,
            type: 'line',
            stroke: obj.stroke || '#000000',
            strokeWidth: Math.round(((obj.strokeWidth || 1) / effectivePxPerMm) * 100) / 100,
            x1: Math.round((obj.x1 / effectivePxPerMm) * 100) / 100,
            y1: Math.round((obj.y1 / effectivePxPerMm) * 100) / 100,
            x2: Math.round((obj.x2 / effectivePxPerMm) * 100) / 100,
            y2: Math.round((obj.y2 / effectivePxPerMm) * 100) / 100,
            text: obj.customData.label || '',
            initialData: JSON.stringify({
              key: obj.customData.key || '',
              label: obj.customData.label || '',
              type: obj.customData.type || '',
              textTemplate: obj.customData.textTemplate || '',
              position: { x: Math.round((obj.left / effectivePxPerMm) * 100) / 100, y: Math.round((obj.top / effectivePxPerMm) * 100) / 100 },
              Line:[Math.round((obj.x1 / effectivePxPerMm) * 100) / 100, 
                Math.round((obj.y1 / effectivePxPerMm) * 100) / 100, 
                obj.customData.key === 'horizontalLine' ? ((obj.width * obj.scaleX) / effectivePxPerMm) * 100 / 100 : 0, 
                obj.customData.key === 'verticalLine' ? ((obj.height * obj.scaleY) / effectivePxPerMm) * 100 / 100 : 0],
              stroke: obj.stroke || '#000000',
              strokeWidth: obj.customData.strokeWidth,
              width: Math.round(((obj.width * obj.scaleX) / effectivePxPerMm) * 100) / 100,
              height: Math.round(((obj.height * obj.scaleY) / effectivePxPerMm) * 100) / 100,
              strokeDashArray:  obj.customData.strokeDashArray || null, // 实线
              originX: 'left', // 改为left使线条起点位于指定位置
              originY: 'center',
              borderColor: obj.customData.borderColor || '#5E9ED6',
              cornerColor: obj.customData.cornerColor || '#5E9ED6',
              cornerSize: obj.customData.cornerSize || 6,
              transparentCorners: obj.customData.transparentCorners || false,
              hasControls: obj.customData.hasControls || false,
              lockRotation: obj.customData.lockRotation ||  true,
              customType: obj.customData.customType || ''
            }),
          };
        }else if(obj.customType === 'table'){
          // 表格
          console.log("导出的表格数据",obj)
          return {
            ...baseObject,  
            type: 'table',
            initialData: JSON.stringify({
              key: obj.customData.key || '',
              label: obj.customData.label || '',
              type: obj.customData.type || '',
              textTemplate: obj.customData.textTemplate || '',
              position: { x: Math.round((obj.left / effectivePxPerMm) * 100) / 100, y: Math.round((obj.top / effectivePxPerMm) * 100) / 100 },
              rows: obj.customData.rows,
              cols: obj.customData.cols,
              cellWidth: obj.customData.cellWidth * obj.scaleX, // 默认单元格宽度，会被headers中的width覆盖
              cellHeight: obj.customData.cellHeight * obj.scaleY,
              strokeColor: obj.customData.strokeColor || '#000000',
              strokeWidth: obj.customData.strokeWidth* obj.scaleX,
              fieldName: obj.customData.fieldName,
              hasHeader: obj.customData.hasHeader,
              // 注意：不再使用背景色，因为打印机不支持背景色
              headerTextColor: obj.customData.headerTextColor || '#000000', // 默认黑色文本
              headerFontSize: obj.customData.headerFontSize * obj.scaleX,
              headerBold: obj.customData.headerBold || false,
              headers: obj.customData.headers.map(col => ({
                key: col.key,
                label: col.label,
                width: col.width * obj.scaleX,
                type: col.type,
                height: col.height * obj.scaleY, // 使用默认高度
                visible: col.visible
              })),
              tableData: obj.customData.tableData || []
            })
          };
        }

        // 默认情况
        return baseObject;
      });
      console.log("导出的数据结构", exportObjects)
      // 创建简化的导出数据结构，确保所有值都是简单类型
      const exportData = {
        // 基本信息
        version: '1.0',
        templateType: templateTypeValue, // 模板类型
        title: getDefaultTemplateName(templateTypeValue),
        // 画布信息
        canvas: {
          width: Math.round(canvasWidth * 100) / 100,
          height: Math.round(canvasHeight * 100) / 100,
          pxPerMm: Math.round(effectivePxPerMm * 100) / 100,
          direction: canvasWidth > canvasHeight ? 'landscape' : 'portrait'
        },
        // 模板对象
        objects: exportObjects,
        // 导出时间戳
        exportTime: new Date().toISOString(),
        // 帮助信息
        help: {
          // 单位说明
          units: "所有尺寸单位均为毫米(mm)",
          // 坐标系说明
          coordinates: "坐标原点(0,0)位于画布左上角，X轴向右，Y轴向下",
          // 毫米与像素转换说明
          conversion: {
            mmToPixel: "像素 = 毫米 * pxPerMm",
            pixelToMm: "毫米 = 像素 / pxPerMm"
          },
          // 占位符替换说明
          placeholders: "文本中的${data}或${fieldName}将被替换为实际数据"
        }
      };

      try {
        // 使用安全的JSON序列化，避免循环引用
        const jsonString = safeStringify(exportData);
        return jsonString;
      } catch (jsonError) {
        console.error('JSON序列化失败:', jsonError);
        ElMessage.error(`导出模板失败: ${jsonError.message}`);
        return null;
      }
    } catch (error) {
      console.error('导出模板失败:', error);
      ElMessage.error(`导出模板失败: ${error.message}`);
      return null;
    }
  };
  /**
   * 从JSON导入模板 测试
   * @param {string} jsonString JSON格式的模板数据
  */
  const importTemplateFromJson = (jsonString) => {
    if (typeof window === 'undefined' || !window.globalCanvas) {
      console.error('画布未初始化，无法导入模板');
      return false;
    }
    const templateData = JSON.parse(jsonString);
    console.log('开始导入JSON模板数据:', Object.keys(templateData).join(', '));

    // 验证数据格式
    if (!templateData.objects || !templateData.canvas) {
      throw new Error('无效的模板数据格式，缺少objects或canvas属性');
    }
    const { canvas: canvasInfo, objects, fields, templateType: importedTemplateType } = templateData;
    // 提取像素毫米比例，新格式中这是一个简单数值
    const effectivePxPerMm = typeof canvasInfo.pxPerMm === 'number'
      ? canvasInfo.pxPerMm
      : 3.78; // 默认值

    console.log('导入使用的pxPerMm:', effectivePxPerMm);

    // 设置画布尺寸和纸张设置
    if (canvasInfo && canvasInfo.width && canvasInfo.height) {
      try {
        // 1. 首先创建纸张设置对象
        const paperSettings = {
          paperWidth: canvasInfo.width,
          paperHeight: canvasInfo.height,
          pxPerMm: effectivePxPerMm
        };

        // 2. 如果有额外的纸张设置参数，也添加到设置对象中
        if (canvasInfo.direction) {
          paperSettings.printDirection = canvasInfo.direction;
        } else if (canvasInfo.printDirection) {
          paperSettings.printDirection = canvasInfo.printDirection;
        }

        if (canvasInfo.borderType) {
          paperSettings.printBorderType = canvasInfo.borderType;
        } else if (canvasInfo.printBorderType) {
          paperSettings.printBorderType = canvasInfo.printBorderType;
        }

        console.log('准备应用纸张设置:', paperSettings);
        console.log("导入applyPaperSettings对象", applyPaperSettings)
        // 3. 如果有模板类型信息，使用adjustPaperSettingsByType函数设置标准纸张尺寸
        if (importedTemplateType && typeof adjustPaperSettingsByType === 'function') {
          try {
            // 先使用导入的模板类型调整纸张设置
            adjustPaperSettingsByType(importedTemplateType, paperSettings);
            console.log(`已根据模板类型[${importedTemplateType}]调整纸张设置:`, paperSettings);

            // 如果JSON中的尺寸与标准尺寸不同，使用JSON中的尺寸覆盖
            if (canvasInfo.width && canvasInfo.width !== paperSettings.paperWidth) {
              console.log(`覆盖标准宽度(${paperSettings.paperWidth})为JSON指定的宽度:${canvasInfo.width}`);
              paperSettings.paperWidth = canvasInfo.width;
            }

            if (canvasInfo.height && canvasInfo.height !== paperSettings.paperHeight) {
              console.log(`覆盖标准高度(${paperSettings.paperHeight})为JSON指定的高度:${canvasInfo.height}`);
              paperSettings.paperHeight = canvasInfo.height;
            }
          } catch (adjustError) {
            console.warn('根据模板类型调整纸张设置失败:', adjustError);
          }
        }

        // 4. 使用传入的applyPaperSettings函数应用纸张设置
        if (typeof applyPaperSettings === 'function') {
          applyPaperSettings(paperSettings);
          console.log('已使用传入的applyPaperSettings函数更新纸张设置');
        }

        // 确保pxPerMm被正确设置
        if (typeof setPxPerMm === 'function') {
          setPxPerMm(effectivePxPerMm);
          console.log(`已更新像素毫米比例: ${effectivePxPerMm}px/mm`);
        }

        console.log(`纸张设置和画布尺寸已更新: ${canvasInfo.width}mm x ${canvasInfo.height}mm`);
      } catch (sizeError) {
        console.error('设置画布尺寸和纸张设置失败:', sizeError);
        ElMessage.warning(`设置画布尺寸失败: ${sizeError.message}`);
      }
    }
    // 导入对象
    if (objects && Array.isArray(objects)) {
      // 依次添加对象
      for (const obj of objects) {
        const initialData = JSON.parse(obj.initialData)
        console.log("导入的初始数据",initialData)
        handleFieldSelected(initialData)
        if(initialData.type!=='line'){
          printFields[initialData.key] = true;
        }
        if(initialData.type==='table'){
          setTableData(initialData)
        } 
      }
      return true;
    }
  }

  /**
   * 安全的JSON序列化，处理循环引用
   * @param {Object} obj 要序列化的对象
   * @param {Number} maxDepth 最大深度，防止无限嵌套
   * @returns {String} JSON字符串
   */
  const safeStringify = (obj, maxDepth = 20) => {
    // 使用WeakMap存储已经访问过的对象，避免循环引用
    const seen = new WeakMap();

    // 使用JSON.stringify的replacer函数处理对象
    return JSON.stringify(obj, (key, value) => {
      // 跳过Vue内部属性
      if (key.startsWith('_') || key.startsWith('$')) {
        return undefined;
      }

      // 处理非对象值
      if (typeof value !== 'object' || value === null) {
        return value;
      }

      // 处理Date对象
      if (value instanceof Date) {
        return value.toISOString();
      }

      // 检查循环引用
      if (seen.has(value)) {
        return '[循环引用]';
      }

      // 记录当前对象，以便检测循环引用
      seen.set(value, true);

      // 处理数组或对象 - 只拷贝一层，由JSON.stringify递归处理，避免我们自己递归
      if (Array.isArray(value)) {
        // 过滤掉可能导致循环引用的数组元素
        const result = value.map(item => {
          if (typeof item === 'object' && item !== null) {
            // 如果数组元素是对象，只保留简单属性
            if (seen.has(item)) return '[循环引用]';

            // 创建新对象，只包含简单值
            const safeItem = {};
            for (const k in item) {
              if (Object.prototype.hasOwnProperty.call(item, k) &&
                !k.startsWith('_') && !k.startsWith('$')) {
                const propValue = item[k];
                // 只保留简单类型或将对象引用替换为标记
                safeItem[k] = (typeof propValue !== 'object' || propValue === null)
                  ? propValue
                  : '[对象]';
              }
            }
            return safeItem;
          }
          return item;
        });
        return result;
      }

      // 处理普通对象 - 只保留直接属性，不进行递归
      const result = {};
      for (const k in value) {
        if (Object.prototype.hasOwnProperty.call(value, k) &&
          !k.startsWith('_') && !k.startsWith('$')) {
          result[k] = value[k];
        }
      }

      return result;
    }, 2);
  };

  /**
   * 安全的对象替换器，用于深度处理
   */
  const safeReplacer = (obj, seen, maxDepth) => {
    // 注意：该函数已被重构并整合到safeStringify中，保留以防有其他代码引用
    if (maxDepth <= 0) return '[对象过深]';
    if (typeof obj !== 'object' || obj === null) return obj;
    if (seen.has(obj)) return '[循环引用]';

    const result = Array.isArray(obj) ? [] : {};
    seen.set(obj, true);

    if (Array.isArray(obj)) {
      for (let i = 0; i < obj.length; i++) {
        const value = obj[i];
        if (typeof value === 'object' && value !== null) {
          if (maxDepth > 1) {
            result[i] = safeReplacer(value, seen, maxDepth - 1);
          } else {
            result[i] = '[对象过深]';
          }
        } else {
          result[i] = value;
        }
      }
    } else {
      for (const key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key) &&
          !key.startsWith('_') && !key.startsWith('$')) {
          const value = obj[key];
          if (typeof value === 'object' && value !== null) {
            if (maxDepth > 1) {
              result[key] = safeReplacer(value, seen, maxDepth - 1);
            } else {
              result[key] = '[对象过深]';
            }
          } else {
            result[key] = value;
          }
        }
      }
    }

    seen.delete(obj);
    return result;
  };

  return {
    getDefaultTemplateName,
    loadDefaultTemplate,
    loadTemplateData,
    exportTemplateToJson,
    importTemplateFromJson,
  };
}
